﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TeamOPSchoolCup.Domain.POCO;
using TeamOPSchoolCup.Domain.DAL;
using TeamOPSchoolCup.Domain.POCO.Members;
using System.Data;

namespace TeamOPSchoolCup.Domain.Services
{
  public class TeamService
  {
    /* TODO: 
*getResults()
*getTeamResults()
*getRank()
*getBestResult()
*/
    public static List<Team> GetTeams()
    {
      List<Team> teams;
      using(EFDbContext db = new EFDbContext()){
        teams = GetTeams(db);
      }

      return teams;
    }

    public static List<Team> GetTeams(EFDbContext db)
    {
      return db.Teams.Include("Coach").Include("TeamMemberships.Student.Member").ToList();
    }

    public static Team GetTeam(int id)
    {
      Team team;
      using(EFDbContext db = new EFDbContext()){
        team = GetTeam(db, id);
      }

      return team;
    }

    public static Team GetTeam(string name)
    {
      Team team;
      using (EFDbContext db = new EFDbContext())
      {
        team = GetTeam(db, name);
      }
      return team;
    }

    public static Team GetTeam(EFDbContext db, int id)
    {
      return GetTeams(db).Single(x => x.TeamId == id);
    }

    public static Team GetTeam(EFDbContext db, string name)
    {
      return GetTeams(db).Single(x => x.Name == name);
    }

    public static List<Team> GetTeamsByCoach(int coachId)
    {
      List<Team> teams;
      using(EFDbContext db = new EFDbContext()){
        teams = GetTeamsByCoach(db, coachId);
      }

      return teams;
    }

    public static List<Team> GetTeamsByCoach(EFDbContext db, int coachId)
    {
      return db.Teams.Include("Coach").Where(x => x.CoachId == coachId).ToList();
    }

    public enum Historicality { ALL, HISTORIC, CURRENT }
    public static List<Team> GetTeamsByStudent(int studentId, Historicality historicality)
    {
      List<Team> teams;
      using(EFDbContext db = new EFDbContext()){
        teams = GetTeamsByStudent(db, studentId, historicality);
      }

      return teams;
    }

    public static List<Team> GetTeamsByStudent(EFDbContext db, int studentId, Historicality historicality)
    {
      List<Team> teams = db.Teams.Include("Coach").Include("TeamMemberships").Where(x => x.TeamMemberships.Any(y => y.StudentId == studentId)).ToList();
      switch (historicality)
      {
        case Historicality.HISTORIC:
          teams = teams.Where(x => x.TeamMemberships.Any(y => y.StudentId == studentId && DateTime.Today <= y.DateLeft)).ToList();
          break;
        case Historicality.CURRENT:
          teams = teams.Where(x => x.TeamMemberships.Any(y => y.StudentId == studentId && DateTime.Today > y.DateLeft)).ToList();
          break;
        case Historicality.ALL:
          teams = teams.Where(x => x.TeamMemberships.Any(y => y.StudentId == studentId)).ToList();
          break;
      }
      return teams;
    }

    public static List<Team> GetTeamsBySchool(int schoolId)
    {
      List<Team> teams;
      using(EFDbContext db = new EFDbContext()){
        teams = GetTeamsBySchool(db, schoolId);
      }

      return teams;
    }

    public static List<Team> GetTeamsBySchool(EFDbContext db, int schoolId)
    {
      //TODO Need schools, nssfs
      return db.Teams.Include("Coach").ToList();
    }

    public static List<Team> GetTeamsByRegion(int regionId)
    {
      List<Team> teams;
      using(EFDbContext db = new EFDbContext()){
        teams = GetTeamsByRegion(db, regionId);
      }

      return teams;
    }

    public static List<Team> GetTeamsByRegion(EFDbContext db, int regionId)
    {
      //TODO need schools, nssfs
      return db.Teams.Include("Coach").ToList();
    }

    public static bool AddTeam(Team team)
    {
      bool t;
      using(EFDbContext db = new EFDbContext()){
        t = AddTeam(db, team);
      }

      return t;
    }

    public static bool AddTeam(EFDbContext db, Team team)
    {
      //Might have to use custom model
      db.Teams.Add(team);
      return (db.SaveChanges() > 0);
    }

    public static bool UpdateTeam(Team team)
    {
      bool t;
      using(EFDbContext db = new EFDbContext()){
        t = UpdateTeam(db, team);
      }

      return t;
    }

    public static bool UpdateTeam(EFDbContext db, Team team)
    {
      db.Entry(team).State = EntityState.Modified;
      return (db.SaveChanges() > 0);
    }

    public static bool DeactivateAllTeams()
    {
      bool t;
      using(EFDbContext db = new EFDbContext()){
        t = DeactivateAllTeams(db);
      }

      return t;
    }

    public static bool DeactivateAllTeams(EFDbContext db)
    {
      db.Teams.ToList().ForEach(t =>
      {
        t.IsParticipating = false;
        db.Entry(t).State = EntityState.Modified;
      });
      return (db.SaveChanges() > 0);
    }

    public static bool DeactivateTeam(int teamId)
    {
      bool t;
      using(EFDbContext db = new EFDbContext()){
        t = DeactivateTeam(db, teamId);
      }

      return t;
    }

    public static bool DeactivateTeam(EFDbContext db, int teamId)
    {
      Team t = db.Teams.Find(teamId);
      t.IsParticipating = false;
      db.Entry(t).State = EntityState.Modified;
      return (db.SaveChanges() > 0);
    }

    public static bool ActivateTeam(int teamId)
    {
      bool t;
      using (EFDbContext db = new EFDbContext())
      {
        t = ActivateTeam(db, teamId);
      }

      return t;
    }

    public static bool ActivateTeam(EFDbContext db, int teamId)
    {
      Team t = db.Teams.Find(teamId);
      t.IsParticipating = true;
      db.Entry(t).State = EntityState.Modified;
      return (db.SaveChanges() > 0);
    }

    public static List<TeamMembership> GetTeamMemberships(int teamId)
    {
      List<TeamMembership> teamMemberships;
      using (EFDbContext db = new EFDbContext())
      {
        teamMemberships = GetTeamMemberships(db, teamId);
      }

      return teamMemberships;
    }

    public static List<TeamMembership> GetTeamMemberships(EFDbContext db, int teamId)
    {
      return db.TeamMemberships.Where(x => x.TeamId == teamId).ToList();
    }

    public static List<TeamMembership> GetTeamMembershipsByStudent(int studentId)
    {
      List<TeamMembership> teamMemberships;
      using (EFDbContext db = new EFDbContext())
      {
        teamMemberships = GetTeamMembershipsByStudent(db, studentId);
      }
      return teamMemberships;
    }

    public static List<TeamMembership> GetTeamMembershipsByStudent(EFDbContext db, int studentId)
    {
      return db.TeamMemberships.Where(x => x.StudentId == studentId).ToList();
    }

    public static bool AddTeamMembership(int teamId, int studentId)
    {
      bool t;
      using (EFDbContext db = new EFDbContext())
      {
        t = AddTeamMembership(db, teamId, studentId);
      }

      return t;
    }

    public static bool AddTeamMembership(EFDbContext db, int teamId, int studentId)
    {
      Student s = db.Students.Include("TeamMemberships.Team.Sport").Include("Member").Single(x => x.StudentId == studentId);
      Team t = db.Teams.Include("Sport").Single(x => x.TeamId == teamId);
      /* //TODO: Once sport is implemented
       * if (s.TeamMemberShips.Any(x => x.Team.Sport.Equals(t.Sport)) {
        return false;
      }*/
      if (s.Member.Gender != t.Gender)
      {
        return false;
      }
      TeamMembership tm = new TeamMembership { Team = t, Student = s, DateJoined = DateTime.Now, DateLeft = new DateTime(DateTime.Now.Year, 12, 31) };
      db.TeamMemberships.Add(tm);
      return (db.SaveChanges() > 0);
    }

    //Als een teamlid meerdere jaren meedoet in eenzelfde team dan moet een teammembership kunnen verlengd worden
    public static bool ProlongTeamMembership(int teamId, int studentId)
    {
      bool t;
      using (EFDbContext db = new EFDbContext())
      {
        t = ProlongTeamMembership(db, teamId, studentId);
      }

      return t;
    }

    public static bool ProlongTeamMembership(EFDbContext db, int teamId, int studentId)
    {
      //TODO If student isn't active and participating yet, we have to update that TODO
      TeamMembership tm = db.TeamMemberships.Single(x => x.StudentId == studentId && x.TeamId == teamId);
      tm.DateLeft = new DateTime(tm.DateLeft.Year + 1, 12, 31);
      db.Entry(tm).State = EntityState.Modified;
      return (db.SaveChanges() > 0);
    }


    //UD TeamMembership TODO?

    public static List<Student> GetStudents(int teamId)
    {
      List<Student> students;
      using (EFDbContext db = new EFDbContext())
      {
        students = GetStudents(db, teamId);
      }

      return students;
    }

    public static List<Student> GetStudents(EFDbContext db, int teamId)
    {
      return db.Students.Include("TeamMemberships").Where(x => x.TeamMemberShips.Any(y => y.TeamId == teamId && DateTime.Today < y.DateLeft)).ToList();
    }

    public static Coach GetCoach(int teamId)
    {
      Coach c;
      using(EFDbContext db = new EFDbContext()){
        c = GetCoach(db, teamId);
      }

      return c;
    }

    public static Coach GetCoach(EFDbContext db, int teamId)
    {
      return db.Coaches.Include("Teams").Where(x => x.CoachId == db.Teams.Find(teamId).CoachId).First();
    }
  }
}
